/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
 \file		CC_GraphItemProp.h
 \date		june 2010
 \author		TNick

 \brief		Contains the definition of CC_GIP class and related


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read ReadMe.txt and Licence.txt in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 Each drawing has a chain rooted at CC_Draw::GphTyp. The chain consists of
 CC_GIP structures chained together. Each CC_GIP structure is a full set
 of graphical properties. Graphical items, layers and any other element that
 requires graphical properties must use a pointer to a CC_GIP structure.

 Changing graphical properties involves calling methods of CC_GIP class. All
 methods that change properties require a returned pointer to a new CC_GIP
 structure that shall be used from that point forward. Depending on several
 factors returned pointer may be the same or diffrent from the initial pointer
 and initial pointer may be valid or not. To be on the safe side, only returned
 pointer shall be used by caller.

 By convention, first item in a chain for any drawing is default (generic)
 item.

*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef		__CC_GIP_INC__
#define		__CC_GIP_INC__
#ifdef		__cplusplus
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	"../generic/cc_l2d.h"
#include	"CC_Err.h"
#include	"CC_Draw.h"

/*  INCLUDES    ============================================================ */
//
//
//
//

class	CC_Draw;


namespace GIP	{

/// associates a flag with each item present in ITEM structure
enum	ITMBR	{
	/// no member is specified
	NOMEMBER = 0,

	COLOR,
	LINEH,
	LINEW,
	ITFLAGS,

	/// may become handy to know last defined flag
	MAX_ITMBR
	};


/// the set of flags used with ITEM structure
enum	IFLG		{

	/// simply indicate that no flag is set
	NOFLAG = 0,

	/// the item is invisible
	/**
  *	If the flag is set, the item will not be drawn even if it's ancestor
  *	is visible. If not set, the item inherits it's visibility
  *	status from it's parent.
  */
	INVISIBLE = 0x00000001,

	/// the item is not printable
	/**
  *	If the flag is set, the item will not be printed even if it's ancestor
  *	is printable. If not set, the item inherits it's printable
  *	status from it's parent.
  */
	NOTPRINT = 0x00000002,

	/// the item has it's own color set
	/**
  *	If the flag is set, the ITEM::col item holds a valid value.
  *	Otherwise, the item inherits the color from ancestor.
  */
	COLORED = 0x00000004,

	/// the item has it's own line type
	/**
  *	If the flag is set, the ITEM::lnTy item holds a valid value.
  *	Otherwise, the item inherits the line type from ancestor.
  */
	LNTYPED = 0x00000008,

	/// the item has it's own line weight
	/**
  *	If the flag is set, the ITEM::lnTy item holds a valid value.
  *	Otherwise, the item inherits the line weight from ancestor.
  */
	WEIGHTED = 0x00000010,





	/// may become handy to know last defined flag
	MAX_FLG

	};	/* enum GIP */

/// graphical properties for individual properties
/**
 *	This structure is used by the user to specify a full set of properties
 *	or only a subset.
 *	Internally, it is also used by CC_GIP to store a part of it's
 *	properties.
 */
struct	ITEM		{
	/// color used to display this item
	QColor		col;
	/// line type (the pattern)
	unsigned	lnTy;
	/// line weight
	unsigned	lnW;
	/// a set of flags
	IFLG		flg;

bool operator==(const ITEM& it) const
{
return ((col == it.col) && (lnTy == it.lnTy) &&
		(lnW == it.lnW) && (flg == it.flg));
}

	};	/* struct ITEM */

	}	/* namespace GIP */






/// graphical properties for individual properties
/**
*	This class groups common informations about graphical properties of an
*	item (true item, layer, ...). Instead of holding one for each item, for
*	each drawing a pool	is maintained, each item having a reference count.
*
*	A "copy on write" like method is used when properties need to be modified.
*	If there is no item matching requested set of properties, a new one is
*	created.
*/
class	CC_GIP	: CC_L2D {

	//
	//
	//
	//
	/*  DEFINITIONS    --------------------------------------------------------- */

	friend class CC_Graphic;

	/*  DEFINITIONS    ========================================================= */
	//
	//
	//
	//
	/*  DATA    ---------------------------------------------------------------- */
	GIP::ITEM		p;


	/*  DATA    ================================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ----------------------------------------------------------- */

	/// constructor; inserts the element in chain and sets data to 0
private: inline				CC_GIP(CC_Draw* pFthDraw)
	: CC_L2D(&pFthDraw->GphTyp) { memset(&p, 0, sizeof(GIP::ITEM)); }

	/// destructor; will free resources; not virtual;
public:						~CC_GIP(){}


	/// bind an item to a generic GIP
	/**
	*	Shall check if the drawing has at least one graphical item (otherwise
	*	will create a new, default one), will increase it's reference counter
	*	and will return a reference to it.
	*/
public: static 	CCERR::EERRORS		GetGenericItem	(
		CC_Draw*		pD,		/**< the drawing for which this is requested */
		CC_GIP**		pOut,	/**< where should the returned pointer be put */
		CC_Err*			pErr	/**< pointer to corellation error structure */
		);

	/// bind an item to a specific GIP
	/**
	*	Checks if a specific item exists and, if so, returns a reference to it.
	*	If it doesn't, it creates one. In any case, the reference count is
	*	incremented by one.
	*/
public: static 	CCERR::EERRORS		GetSpecificItem	(
		CC_Draw*		pD,		/**< the drawing for which this is requested */
		GIP::ITEM*		pRq,	/**< requested values */
		GIP::ITMBR		val_flg,/**< which elements are valid; the elements
		that are not marked will be retrieved as if a call to
		GetGenericItem would have been issued */
		GIP::IFLG		flg_mask,/**< tell what flags are valid in ITMBR */
		CC_GIP**		pOut,	/**< where should the returned pointer be put */
		CC_Err*			pErr	/**< pointer to corellation error structure */
		);


	/*		C O L O R		*/
	/// change the color of an item
public: inline	CCERR::EERRORS		setColor		(
		QColor			Acol,	/**< new color to set*/
		CC_Err*			pErr	/**< pointer to corellation error structure */
		){
		Q_UNUSED(pErr);
		p.col = Acol;
		return CCERR::ERR_STATUS;
		};
	/// change the color of an item
public: inline	CCERR::EERRORS		setColor		(
		QRgb			col,	/**< new color to set*/
		CC_Err*			pErr	/**< pointer to corellation error structure */
		){
		Q_UNUSED(pErr);
		p.col.setRgb(col);
		return CCERR::ERR_STATUS;
		};
	/// get the color of an item
	/**
*	@return		an error code if the element is inherited
*/
public: inline	CCERR::EERRORS		Color		(
		QRgb*			col		/**< the color is returned here */
		){
		if (p.flg & GIP::COLORED)	{
			*col = p.col.rgb();
			return CCERR::ERR_SUCCESS;}
		else
			return CCERR::ERR_STATUS;
		};
	/// get the color of an item
	/**
*	@return		an error code if the element is inherited
*/
public: inline	CCERR::EERRORS		Color		(
		QColor*			col		/**< the color is returned here */
		){
		if (p.flg & GIP::COLORED)	{
			col->setRgb(p.col.rgb());
			return CCERR::ERR_SUCCESS;}
		else
			return CCERR::ERR_STATUS;
		};


	/*		L I N E   T Y P E       */
	/// change the line type of an item
public: inline	CCERR::EERRORS		setLinePattern		(
		unsigned		lnty,	/**< new line type to set*/
		CC_Err*			pErr	/**< pointer to corellation error structure */
		);
	/// get the line type of an item
	/**
*	@return		an error code if the element is inherited
*/
public: inline	CCERR::EERRORS		LinePattern		(
		unsigned*		lnty	/**< the line type is returned here */
		){
		if (p.flg & GIP::COLORED)	{
			*lnty = p.lnTy;
			return CCERR::ERR_SUCCESS;}
		else
			return CCERR::ERR_STATUS;
		};


	/*		L I N E   W E I G H T       */
	/// change the line weight of an item
public: inline	CCERR::EERRORS		setLineWeight		(
		unsigned		lnw,	/**< new line weight to set*/
		CC_Err*			pErr	/**< pointer to corellation error structure */
		);

	/// get the line weight of an item
	/**
*	@return		an error code if the element is inherited
*/
public: inline	CCERR::EERRORS		LineWeight		(
		unsigned*		lnw		/**< the line weight is returned here */
		){
		if (p.flg & GIP::COLORED)	{
			*lnw = p.lnW;
			return CCERR::ERR_SUCCESS;}
		else
			return CCERR::ERR_STATUS;
		};


	/*		V I S I B I L I T Y       */
	/// change the visibility of an item
public: inline	CCERR::EERRORS		setVisible		(
		bool			bVis,	/**< new visibility to set */
		CC_Err*			pErr	/**< pointer to corellation error structure */
		);
	/// get the visibility of an item
	/**
*	@return		false if invisible, true if inherited
*/
public: inline	bool				Visible		(void)
		{	return	((p.flg & GIP::INVISIBLE) == 0);	};


	/*		P R I N T - A B L E		*/
	/// change the visibility of an item
public: inline	CCERR::EERRORS		setPrintable		(
		bool			bVis,	/**< new printable status to set */
		CC_Err*			pErr	/**< pointer to corellation error structure */
		);
	/// get the printable status of an item
	/**
*	@return		false if not printable, true if inherited
*/
public: inline	bool				Printable		(void)
		{	return	((p.flg & GIP::NOTPRINT) == 0);	};





	/*  FUNCTIONS    =========================================================== */
	//
	//
	//
	//

	};	/*	class	CC_GIP	*/
//
//
//
//
#endif	//	__cplusplus
#endif	//	__CC_GIP_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
